package net.i2p.crypto; import java.lang.reflect.Constructor; import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.Provider; import java.security.Security; import java.security.spec.ECField; import java.security.spec.ECFieldFp; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import net.i2p.util.NativeBigInteger; /** * Constants for elliptic curves, from NIST FIPS 186-4 (2013) / ANSI X9.62 * * @since 0.9.9 */ final class ECConstants { private static final boolean DEBUG = false; private static void log(String s) { log(s, null); } private static void log(String s, Throwable t) { if (DEBUG) { System.out.println("ECConstants: " + s); if (t != null) t.printStackTrace(); } } private static final boolean BC_AVAILABLE; static { boolean loaded; if (Security.getProvider("BC") == null) { try { Class<?> cls = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); Constructor<?> con = cls.getConstructor(); Provider bc = (Provider)con.newInstance(); Security.addProvider(bc); log("Added BC provider"); loaded = true; } catch (Exception e) { log("Unable to add BC provider", e); loaded = false; } } else { log("BC provider already loaded"); loaded = true; } BC_AVAILABLE = loaded; } public static boolean isBCAvailable() { return BC_AVAILABLE; } private static class ECParms { public final String ps, ns, ss, bs, gxs, gys; private static final BigInteger A = new NativeBigInteger("-3"); private static final int H = 1; /** * P and N in decimal, no spaces; * Seed, B, Gx, Gy in hex, spaces allowed */ public ECParms(String pss, String nss, String sss, String bss, String gxss, String gyss) { ps = pss; ns = nss; ss = sss; bs = bss; gxs = gxss; gys = gyss; } public ECParameterSpec genSpec() { BigInteger pb = new NativeBigInteger(ps); BigInteger nb = new NativeBigInteger(ns); BigInteger sb = new NativeBigInteger(ss.replace(" ", ""), 16); BigInteger bb = new NativeBigInteger(bs.replace(" ", ""), 16); BigInteger gxb = new NativeBigInteger(gxs.replace(" ", ""), 16); BigInteger gyb = new NativeBigInteger(gys.replace(" ", ""), 16); BigInteger ab = new NativeBigInteger(A.mod(pb)); ECField field = new ECFieldFp(pb); EllipticCurve curve = new EllipticCurve(field, ab, bb, sb.toByteArray()); ECPoint g = new ECPoint(gxb, gyb); return new ECParameterSpec(curve, g, nb, H); } } /* D.1.2 Curves over Prime Fields For each prime p, a pseudo-random curve E : y**2 = x**3 -3x +b (mod p) of prime order n is listed 4. (Thus, for these curves, the cofactor is always h = 1.) The following parameters are given: The selection a a = -3 for the coefficient of x was made for reasons of efficiency; see IEEE Std 1363-2000. * The prime modulus p * The order n * The 160-bit input seed SEED to the SHA-1 based algorithm (i.e., the domain parameter seed) * The output c of the SHA-1 based algorithm * The coefficient b (satisfying b**2 c = -27 (mod p)) * The base point x coordinate G x * The base point y coordinate G y The integers p and n are given in decimal form; bit strings and field elements are given in hexadecimal. */ /* D.1.2.1 Curve P-192 p= 6277101735386680763835789423207666416083908700390324961279 n= 6277101735386680763835789423176059013767194773182842284081 SEED = 3045ae6f c8422f64 ed579528 d38120ea e12196d5 c= 3099d2bb bfcb2538 542dcd5f b078b6ef 5f3d6fe2 c745de65 b= 64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1 Gx= 188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012 Gy= 07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811 */ /* private static final ECParms PARM_P192 = new ECParms( // P N Seed B Gx Gy "6277101735386680763835789423207666416083908700390324961279", "6277101735386680763835789423176059013767194773182842284081", "3045ae6f c8422f64 ed579528 d38120ea e12196d5", "64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1", "188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012", "07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811" ); */ /* D.1.2.3 Curve P-256 p= 1157920892103562487626974469494075735300861434152903141955 33631308867097853951 n= 115792089210356248762697446949407573529996955224135760342 422259061068512044369 SEED = c49d3608 86e70493 6a6678e1 139d26b7 819f7e90 c= 7efba166 2985be94 03cb055c 75d4f7e0 ce8d84a9 c5114abc af317768 0104fa0d b= 5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b Gx= 6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296 Gy= 4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5 */ private static final ECParms PARM_P256 = new ECParms( // P N Seed B Gx Gy "1157920892103562487626974469494075735300861434152903141955" + "33631308867097853951", "115792089210356248762697446949407573529996955224135760342" + "422259061068512044369", "c49d3608 86e70493 6a6678e1 139d26b7 819f7e90", "5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6" + "3bce3c3e 27d2604b", "6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0" + "f4a13945 d898c296", "4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece" + "cbb64068 37bf51f5" ); /* D.1.2.4 Curve P-384 p= 3940200619639447921227904010014361380507973927046544666794 8293404245721771496870329047266088258938001861606973112319 n= 3940200619639447921227904010014361380507973927046544666794 6905279627659399113263569398956308152294913554433653942643 SEED = a335926a a319a27a 1d00896a 6773a482 7acdac73 c= 79d1e655 f868f02f ff48dcde e14151dd b80643c1 406d0ca1 0dfe6fc5 2009540a 495e8042 ea5f744f 6e184667 cc722483 b= b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef Gx= aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7 G y= 3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f */ private static final ECParms PARM_P384 = new ECParms( // P N Seed B Gx Gy "3940200619639447921227904010014361380507973927046544666794" + "8293404245721771496870329047266088258938001861606973112319", "3940200619639447921227904010014361380507973927046544666794" + "6905279627659399113263569398956308152294913554433653942643", "a335926a a319a27a 1d00896a 6773a482 7acdac73", "b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112" + "0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef", "aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98" + "59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7", "3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c" + "e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f" ); /* D.1.2.5 Curve P-521 p= 686479766013060971498190079908139321726943530014330540939 446345918554318339765605212255964066145455497729631139148 0858037121987999716643812574028291115057151 n= 686479766013060971498190079908139321726943530014330540939 446345918554318339765539424505774633321719753296399637136 3321113864768612440380340372808892707005449 SEED = d09e8800 291cb853 96cc6717 393284aa a0da64ba c= 0b4 8bfa5f42 0a349495 39d2bdfc 264eeeeb 077688e4 4fbf0ad8 f6d0edb3 7bd6b533 28100051 8e19f1b9 ffbe0fe9 ed8a3c22 00b8f875 e523868c 70c1e5bf 55bad637 b= 051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00 Gx= c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66 Gy= 118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650 */ private static final ECParms PARM_P521 = new ECParms( "686479766013060971498190079908139321726943530014330540939" + "446345918554318339765605212255964066145455497729631139148" + "0858037121987999716643812574028291115057151", "686479766013060971498190079908139321726943530014330540939" + "446345918554318339765539424505774633321719753296399637136" + "3321113864768612440380340372808892707005449", "d09e8800 291cb853 96cc6717 393284aa a0da64ba", "051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b" + "99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd" + "3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00", "c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139" + "053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127" + "a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66", "118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449" + "579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901" + "3fad0761 353c7086 a272c240 88be9476 9fd16650" ); /** * Generate a spec from a curve name * @return null if fail */ private static ECParameterSpec genSpec(String name) { // convert the ECGenParameterSpecs to ECParameterSpecs for several reasons: // 1) to check availability // 2) efficiency // 3) SigUtil must cast the AlgorithmParameterSpec to a ECParameterSpec // to convert a I2P key to a Java key. Sadly, a ECGenParameterSpec // is not a ECParameterSpec. try { AlgorithmParameters ap; try { ap = AlgorithmParameters.getInstance("EC"); } catch (GeneralSecurityException e) { if (BC_AVAILABLE) { log("Named curve " + name + " is not available, trying BC", e); ap = AlgorithmParameters.getInstance("EC", "BC"); log("Fallback to BC worked for named curve " + name); } else { throw e; } } ECGenParameterSpec ecgps = new ECGenParameterSpec(name); ap.init(ecgps); ECParameterSpec rv = ap.getParameterSpec(ECParameterSpec.class); log("Named curve " + name + " loaded"); return rv; } catch (GeneralSecurityException e) { log("Named curve " + name + " is not available", e); return null; } } /** * Tries curve name1, then name2, then creates new from parms. * @param name2 null to skip * @param parms null to skip * @return null if all fail */ private static ECParameterSpec genSpec(String name1, String name2, ECParms parms) { ECParameterSpec rv = genSpec(name1); if (rv == null && name2 != null) { rv = genSpec(name2); if (rv == null && parms != null) { rv = parms.genSpec(); if (rv != null) log("Curve " + name2 + " created"); } } return rv; } // standard curve names // first is OpenJDK 6/7 // second is BC //public static final ECParameterSpec P192_SPEC = genSpec("secp192r1", "P-192", PARM_P192); public static final ECParameterSpec P256_SPEC = genSpec("secp256r1", "P-256", PARM_P256); public static final ECParameterSpec P384_SPEC = genSpec("secp384r1", "P-384", PARM_P384); public static final ECParameterSpec P521_SPEC = genSpec("secp521r1", "P-521", PARM_P521); // Koblitz //public static final ECParameterSpec K163_SPEC = genSpec("sect163k1", "K-163", null); //public static final ECParameterSpec K233_SPEC = genSpec("sect233k1", "K-233", null); //public static final ECParameterSpec K283_SPEC = genSpec("sect283k1", "K-283", null); //public static final ECParameterSpec K409_SPEC = genSpec("sect409k1", "K-409", null); //public static final ECParameterSpec K571_SPEC = genSpec("sect571k1", "K-571", null); }